#include "EventLoop.h"
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/timerfd.h>
#include <algorithm>

using namespace std;
itimerspec resetTimer(int fd, int m) {
    struct itimerspec ts {0};
    ts.it_value.tv_sec = m;
    ts.it_value.tv_nsec = 0;
    if (timerfd_settime(fd, 0, &ts, nullptr) == -1) {
        perror("timerfd_settime");
    }
    return ts;
}
EventLoop::EventLoop(int maxEvent) : ep_{maxEvent} {
    wakeupFd_ = eventfd(0, 0);
    if (wakeupFd_ == -1) {
        perror("eventfd");
        exit(1);
    }
    wakeCh_ = new Channel(&ep_, wakeupFd_);
    wakeCh_->enableReading();
    wakeCh_->setReadCb(std::bind(&EventLoop::handleWakeup, this));
    ep_.updateChannel(wakeCh_);

    timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
    if (timerFd_ == -1) {
        perror("timerfd_create");
    }
    // 设置定时器参数，每隔5秒触发一次
    resetTimer(timerFd_, 200000);
    // return ts;

    timerCh_ = new Channel(&ep_, timerFd_);
    timerCh_->enableReading();
    timerCh_->setReadCb(std::bind(&EventLoop::handleTimer, this));
    ep_.updateChannel(timerCh_);
}

EventLoop::~EventLoop() {
    cout << "EventLoop::~EventLoop()" << endl;
    close(wakeupFd_);
    close(timerFd_);
    delete wakeCh_;
    delete timerCh_;
}

void EventLoop::Loop() {
    isRunning_ = true;
    threadId_ = this_thread::get_id();
    cout << __FILE__ << __LINE__ << " EventLoop::Loop() threadId_ = " << threadId_ << endl;
    while (isRunning_) {
        auto channels = ep_.Wait();
        for (auto ch : channels) {
            ch->handleEvent();
        }
    }
    cout << "EventLoop::Loop() end" << endl;
}
void EventLoop::stop() {
    isRunning_ = false;
    // 唤醒之后，处理完任务队列后自动退出
    wakeup();
}
bool EventLoop::isIOThread() {
    auto curId = this_thread::get_id();
    return curId == threadId_;
}
void EventLoop::addTask(std::function<void()> task) {
    {
        unique_lock<mutex> mtx(queMtx_);
        tasks_.push(task);
    }
    wakeup();
}

void EventLoop::wakeup() {
    uint64_t wake = 1;
    int len = write(wakeupFd_, &wake, sizeof(uint64_t));
}
void EventLoop::handleWakeup() {
    // 先把数据读出来，否则下次还会通知
    uint64_t wake;
    read(wakeupFd_, &wake, sizeof(uint64_t));
    // 被唤醒后循环执行任务队列
    function<void()> task;
    while (1) {
        {
            unique_lock<mutex> mtx(queMtx_);
            if (tasks_.empty()) {
                break;
            }
            task = std::move(tasks_.front());
            tasks_.pop();
        }
        task();
    }
}

void EventLoop::handleTimer() {
    // 重新设置定时器
    resetTimer(timerFd_, duration_);
    // 清理超时链接
    cout << this_thread::get_id() << " timer: " << endl;
    for(auto it = fds_.begin(); it != fds_.end();) {
        auto [fd, conn] = *it;
        if (conn->isTimeout(5)) {
            cout << "timeout: " << fd << "\t";
            it = fds_.erase(it);
            conn->closeConn();
        } else {
            ++it;
        }
    }
}
/*
std::pair<const int, Connection*>& std::pair<const int, Connection*>::operator=(const std::pair<const int, Connection*>&)’ 
is implicitly declared as deleted because 
‘std::pair<const int, Connection*>’ declares a move constructor or move assignment operator
*/